package com.yuncheng.spcyApi.flow;

import cn.hutool.core.collection.CollectionUtil;
import com.yuncheng.oaApi.entity.OaJobEntity;
import org.apache.commons.collections.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yuncheng.spcyApi.constant.flow.FlowNodeConstant;
import com.yuncheng.spcyApi.constant.common.SpcyConstant;
import com.yuncheng.spcyApi.entity.*;
import com.yuncheng.exception.BusinessException;
import com.yuncheng.spcyApi.service.IOaJobService;
import com.yuncheng.spcyApi.service.ISysFlowNodeService;
import com.yuncheng.spcyApi.service.ISysJobService;
import com.yuncheng.spcyApi.utils.GetCurrentUserUtils;
import com.yuncheng.spcyApi.utils.GetUuIdUtils;
import com.yuncheng.vo.CurrentUserVo;
import com.yuncheng.spcyApi.vo.common.Result;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component(value = "spcyOaFlowService")
public class OaFlowService {

    @Resource
    private IOaJobService oaJobService;


    @Resource
    private ISysJobService sysJobService;

    @Resource
    @Lazy
    private ISysFlowNodeService sysFlowNodeService;

    @Resource
    @Lazy
    private FlowNodeDbrService flowNodeDbrService;

    /**
     * 获取流程模板第一个环节id
     * @param lcmbCode
     * @return
     */
    public String getFirstNodeId(String lcmbCode){
        //获取流程模板的第一个环节
        SysFlowTemple code = sysFlowNodeService.getCode(lcmbCode);

        List<SysFlowNode> node = sysFlowNodeService.getFirstNode(code.getId());
        if (CollectionUtil.isNotEmpty(node)){
            return node.get(0).getId();
        }
        return "";
    }

    public Result createProcess(String lcmbCode, String pid, CurrentUserVo currentUser){

        //获取流程模板的第一个环节
        SysFlowTemple code = sysFlowNodeService.getCode(lcmbCode);

        List<SysFlowNode> node = sysFlowNodeService.getFirstNode(code.getId());

        List<OaJobEntity> jobList = oaJobService.list(new LambdaQueryWrapper<OaJobEntity>()
                .eq(OaJobEntity::getFpid, pid)
                .eq(OaJobEntity::getFnodeid, node.get(0).getId()));
        if (CollectionUtils.isNotEmpty(jobList)){
            return Result.error("当前申请事项环节["+node.get(0).getFjdmc()+"】已经初始化了!");
        }

        Result result = createJob(lcmbCode,pid,"",node.get(0),null,null,currentUser);
        if (!result.isSuccess()){
            throw new BusinessException(result.getMessage());
        }

        return result;
    }

    /**
     * 创建流程
     * @param lcmbCode 流程编码code
     * @param pid 业务id
     * @param dbrId 待办人id
     * @param nowNode 当前节点对象
     * @param nowJob 当前流程对象
     * @param nextNodeId 下一环节id
     * @param currentUser 当前登陆人
     * @return
     */
    public Result createJob(String lcmbCode, String pid, String dbrId, SysFlowNode nowNode, OaJobEntity nowJob, String nextNodeId, CurrentUserVo currentUser){
        return this.createJob(lcmbCode, pid, dbrId, nowNode, nowJob, nextNodeId, currentUser, null);
    }

    /**
     * 创建流程
     * @param lcmbCode 流程编码code
     * @param pid 业务id
     * @param dbrId 待办人id
     * @param nowNode 当前节点对象
     * @param nowJob 当前流程对象
     * @param nextNodeId 下一环节id
     * @param currentUser 当前登陆人
     * @param dbrMap 待办人对象（dbrId,dbr）
     * @return
     * {
     *     result.OaJob
     * }
     */
    public Result createJob(String lcmbCode, String pid, String dbrId, SysFlowNode nowNode, OaJobEntity nowJob, String nextNodeId, CurrentUserVo currentUser, Map dbrMap){

        String dbr = "";
        if (dbrMap == null){
            dbrMap = this.verifryNextDbr(lcmbCode, pid, dbrId, nowNode, nowJob, nextNodeId, currentUser);
        }
        dbrId = dbrMap.get("dbrId").toString();
        dbr = dbrMap.get("dbr").toString();
        nowNode = (SysFlowNode) dbrMap.get("nowNode");

        String fnodeid = nowNode.getId();
        String fblfs = nowNode.getFblfs();
        String fjdmc = nowNode.getFjdmc();
        String lcmc = sysFlowNodeService.getCode(lcmbCode).getFlcmc();

        OaJobEntity job = new OaJobEntity();
        job.setId(GetUuIdUtils.ReplaceUuId());
        job.setFpid(pid);
        job.setFblfs(fblfs);
        job.setFhjmc(fjdmc);

        if(nowJob == null){
            job.setFsyhjid("");
        }else {
            job.setFsyhjid(nowJob.getId());
        }

        job.setFlcmc(lcmc); // 流程名称
        job.setFnodeid(fnodeid); // 结点id

        // 发送人
        if(currentUser != null) {
            job.setFfsrid(currentUser.getId());
            job.setFfsrmc(currentUser.getName());
        }

        job.setFfssj(new Date());

        job.setFdbr(dbr);
        job.setFdbrid(dbrId);

        job.setFydbr(dbr);
        job.setFydbrid(dbrId);

        job.setFblzt(SpcyConstant.BLZT_DB);
        job.setFywlx(SpcyFlowConstant.PROCESS_BUSINESS_YWLX_OA);

        oaJobService.save(job);
        return Result.ok(job);
    }


    /**
     * 判断下一环节是否存在待办人
     * @param lcmbCode 流程编码code
     * @param pid 业务id
     * @param dbrId 待办人id
     * @param nowNode 当前节点对象
     * @param nowJob 当前流程对象
     * @param nextNodeId 下一环节id
     * @param currentUser 当前登陆人
     * @return
     * {
     *     dbrId: 待办人id
     *     dbr: 待办人
     *     nowNode: 流程结点
     *     isEnd: true/false
     * }
     */
    public Map verifryNextDbr(String lcmbCode, String pid, String dbrId, SysFlowNode nowNode, OaJobEntity nowJob, String nextNodeId, CurrentUserVo currentUser){

        Map resultMap = new HashMap();

        if (nowNode == null) {
            if (StringUtils.isNotBlank(nextNodeId)) {
                nowNode = sysFlowNodeService.getById(nextNodeId);
            }

            // 如果nowJob 不为空
            if (StringUtils.isBlank(nextNodeId) && nowJob != null) {
                /**
                 * 根据当前结点id,获取下结点id
                 */
                String fnodeid1 = nowJob.getFnodeid();
                List<SysFlowNode> nextNodeList = sysFlowNodeService.getNextNode(fnodeid1);
                if (CollectionUtil.isEmpty(nextNodeList)) {

                    resultMap.put("dbrId", "流程结束");
                    resultMap.put("dbr", "流程结束");
                    resultMap.put("nowNode", null);
                    resultMap.put("isEnd", true);
                    return resultMap;
                }

                if (nextNodeList.size() > 1) {
                    if (StringUtils.isBlank(nextNodeId)) {
                        throw new BusinessException("请选择要提交环节！");
                    } else {
                        nowNode = sysFlowNodeService.getById(nextNodeId);
                    }
                } else if (nextNodeList.size() == 1) {
                    nowNode = nextNodeList.get(0);
                }
            }
        }

        if (nowNode == null) {
            throw new BusinessException("请提供" + lcmbCode + "的流程结点！");
        }

        nextNodeId = nowNode.getId();

        String dbr = ""; // 待办人

        if (StringUtils.isBlank(dbrId)) {
            // 待办人和原待办人
            Integer fsfcjdpzhq = nowNode.getFsfcjdpzhq();
            // 是否从结点配置获取待办人: 0是/1否
            if (fsfcjdpzhq.equals(FlowNodeConstant.SFZD_YES)) {
                Map nodeDbrids = getNodeDbrids(lcmbCode, nextNodeId, pid);
                dbrId = nodeDbrids.get("dbrId").toString();
                dbr = nodeDbrids.get("dbr").toString();
            } else {
                String fjdmc = nowNode.getFjdmc();
                Map dbrMap = this.getBtFlowNodeDbr(lcmbCode, pid, fjdmc);
                dbrId = dbrMap.get("dbrId").toString();
                dbr = dbrMap.get("dbr").toString();
            }
        }else {
            dbr = flowNodeDbrService.getDbrNameById(dbrId);
        }

        if (StringUtils.isBlank(dbrId)){
            throw new BusinessException("获取不到环节待办人！");
        }

        resultMap.put("dbrId", dbrId);
        resultMap.put("dbr", dbr);
        resultMap.put("nowNode", nowNode);
        resultMap.put("isEnd", false);
        return resultMap;
    }


    /**
     * 获取当前结点待办人
     * @param nowNodeid 当前节点id
     * @return
     */
    public Map getNodeDbrids(String lcmbCode, String nowNodeid, String pid){

        SysFlowNode sysFlowNode = sysFlowNodeService.getById(nowNodeid);

        Integer fsfcjdpzhq = sysFlowNode.getFsfcjdpzhq(); //是否从节点配置获取待办人
        String fblbmlx = sysFlowNode.getFblbmlx(); //办理部门类型
        String fblbmid = sysFlowNode.getFblbmid(); //办理部门id

        String fblgwid = sysFlowNode.getFblgwid(); //办理岗位id

        String fblrid = sysFlowNode.getFblrid(); //办理人id
        Integer fsfzdblr = sysFlowNode.getFsfzdblr(); //是否指定办理人
        Integer fsfzddlr= sysFlowNode.getFsfzddlr(); //是否指定登陆人为办理人

        Map map = new HashMap();

        //是否从节点配置获取待办人：0是 / 1否  为0则读取当前节点配置的环节办理人
        if (fsfcjdpzhq.equals(FlowNodeConstant.SFZD_YES)){

            //如果指定办理人 直接返回指定人
            if (fsfzdblr.equals(FlowNodeConstant.SFZD_YES)){
                if (StringUtils.isBlank(fblrid)){
                    throw new BusinessException("查询不到指定办理人");
                }
                String dbrName = flowNodeDbrService.getDbrNameById(fblrid);
                map.put("dbr",dbrName);
                map.put("dbrId",fblrid);
                return map;
            }

            //如果指定当前登陆人 则返回当前登录用户
            if (fsfzddlr.equals(FlowNodeConstant.SFZD_YES)){
                CurrentUserVo currentUser = GetCurrentUserUtils.getCurrentUser();
                if (currentUser == null){
                    throw new BusinessException("当前登录已失效！请重新登录！");
                }
                String dbrid = currentUser.getId();
                String dbrname = currentUser.getName();
                map.put("dbr",dbrname);
                map.put("dbrId",dbrid);
                return map;
            }

            // 根据办理部门id+岗位id-获取对应的人员
            Map dbrByBmGw = getDbrByBmGw(fblbmid, fblgwid);

            //如果办理部门类型为 指定 则待办人 进入 根据部门和岗位判断
            if (fblbmlx.equals(FlowNodeConstant.BLJD_BLBM_ZD)){
                return dbrByBmGw;

                //在判断 办理部门类型为 不指定 则 待办人 根据 办理岗位id 来 判断
            }else if(fblbmlx.equals(FlowNodeConstant.BLJD_BLBM_BZD)){

                //否则根据办理部门id返回待办人
                return dbrByBmGw;
            }else if (fblbmlx.equals(FlowNodeConstant.BLJD_BLBM_DQBM)){

                return dbrByBmGw;
            }
        }else {

            String fjdmc = sysFlowNode.getFjdmc();
            this.getBtFlowNodeDbr(lcmbCode, pid, fjdmc);

            return map;
        }
        return map;
    }


    /**
     * 不从流程配置中获取待办人-根据不同流程-获取不同流程对应结点的待办人
     * @param lcmbCode 流程编码
     * @param pid 业务id
     * @param fjdmc 结点名称
     * @return
     */
    private Map getBtFlowNodeDbr(String lcmbCode, String pid,String fjdmc){

        Map resultMap = new HashMap();
        resultMap.put("dbrId", "");
        resultMap.put("dbr", "");
        return resultMap;
    }

    /* 根据办理部门id 和 办理岗位id 判断返回待办人
     * @param fblbmid
     * @param fblgwid
     * @return
     */
    private Map getDbrByBmGw(String fblbmid,String fblgwid){
        Map map = new HashMap();
        String dbr="";
        String dbrid="";
        //null null  办理部门id和办理岗位id都为空 直接返回为空
        if (StringUtils.isBlank(fblbmid) && StringUtils.isBlank(fblgwid)){
            map.put("dbr",dbr);
            map.put("dbrId",dbrid);
            return map;
        }
        //null not  办理部门id为空 办理岗位id不为空  返回当前办理岗位的所有人
        if (StringUtils.isBlank(fblbmid) && StringUtils.isNotBlank(fblgwid)){
            Map dbrByGwid = flowNodeDbrService.getDbrByGwid(fblgwid);
            return dbrByGwid;
        }
        //not null 办理部门id不为空 办理岗位id为空  返回当前部门id的所有人
        if (StringUtils.isNotBlank(fblbmid) && StringUtils.isBlank(fblgwid)){
            Map dbrByBmid = flowNodeDbrService.getDbrByBmid(fblbmid);
            return dbrByBmid;
        }
        // not not 办理部门id 和办理岗位id 都不为空 则返回当前部门下 当前办理岗位的用户
        if (StringUtils.isNotBlank(fblbmid) && StringUtils.isNotBlank(fblgwid)){

            // 先判断办理岗位id 是不是分管领导
            List<SysJob> sysJobs = sysJobService.list(new LambdaQueryWrapper<SysJob>().eq(SysJob::getId, fblgwid));
            String jobName = sysJobs.get(0).getJobName();
            if (jobName.equals(FlowNodeConstant.ROLE_NAME_FGLD)){
                return flowNodeDbrService.getFgldByDeptId(fblbmid);
            }else {
                return flowNodeDbrService.getdbrByDeptName(fblbmid, fblgwid);
            }
        }

        map.put("dbr",dbr);
        map.put("dbrId",dbrid);
        return map;
    }
}
